import sys

from wxauto import WeChat
import re
import os
import time
import traceback
from tinydb import TinyDB


# 监听间隔，单位：秒（每隔多少秒检查一下是否有新消息）
LISTEN_INTERVAL = 5
HOME = os.environ['USERPROFILE']
COUNT_DB = TinyDB(HOME + '\\.caiwu\\chatbot.json')

def parse_arguments():
    """解析命令行参数，返回监听目标列表"""
    if len(sys.argv) < 1:  # 检查参数数量[1,5,8](@ref)
        print("使用方法: python chatbot.py 监听对象1 监听对象2 ...")
        sys.exit(1)
    return sys.argv[1:]  # 返回所有监听目标参数[1,8](@ref)

def handleMsg(wx, who, msg):
    if msg == "/撤销":
        reset(wx)
    elif msg == "/清账":
        clear(wx)
    elif msg == "/查询":
        search(wx, False)
    elif msg == "/精确查询":
        search(wx, True)
    elif msg.startswith("+") or msg.startswith("-"):
        handleMoneyMsg(wx, who, msg)

def search(wx, flag):
    output = []
    count = lastCount()
    output.append(f"群余额{count['sum']}")
    counts = COUNT_DB.all()
    for count in counts:
        if flag:
            output.append(f"{count['who']}: {count['content']}")
        else:
            output.append(f"{count['content']}")
    wx.SendMsg("\n".join(output))


def clear(wx):
    COUNT_DB.truncate()
    wx.SendMsg("已清空")


def reset(wx):
    all_docs = COUNT_DB.all()
    if not all_docs:
        wx.SendMsg("没有可撤回数据")
        return
    last_doc_id = max(doc.doc_id for doc in all_docs)
    if last_doc_id == 1:
        MONEY = 0
    else:
        MONEY = all_docs[last_doc_id - 2]['sum']

    count = all_docs[last_doc_id - 1]
    COUNT_DB.remove(doc_ids=[last_doc_id])
    output = []
    output.append(f"撤销{count['content']}")
    output.append(f"当前余额{MONEY}")
    if count['remark']:
        output.append(f"备注：{all_docs[last_doc_id - 2]['remark']}")
    wx.SendMsg("\n".join(output))

def lastCount():
    all_docs = COUNT_DB.all()
    if not all_docs:
        return {'sum': 0}
    last_doc_id = max(doc.doc_id for doc in all_docs)
    count = all_docs[last_doc_id - 1]
    return count

def handleMoneyMsg(wx, who, msg):
    # 匹配金额和备注的正则表达式
    pattern = r"^([+-]\d+(?:\.\d+)?(?:\*\d+\.?\d*)?)\s*(.*?)$"
    match = re.match(pattern, msg)

    if not match:
        return

    amount_str, remark = match.groups()
    remark = remark.strip()

    # 解析金额计算逻辑
    amount_part = amount_str[1:]  # 去掉开头的+号
    # 修改后（支持浮点数计算）
    if "*" in amount_part:
        base_str, multiplier_str = amount_part.split("*")
        base = float(base_str)
        multiplier = float(multiplier_str)
    else:
        base = float(amount_part)
        multiplier = 1.0

    # 计算并更新余额
    calculated = base * multiplier

    count = lastCount()

    if msg.startswith("+"):
        MONEY = count['sum'] + calculated
    else:
        MONEY = count['sum'] - calculated

    # 构造输出结果
    output = []
    output.append(f"当前余额 {amount_str} = {MONEY:.2f}")
    if remark:
        output.append(f"备注：{remark}")
    COUNT_DB.insert({'count': round(calculated, 2), 'remark': remark, 'content': msg, 'sum': round(MONEY, 2), 'who': who + time.strftime('%m-%d %H:%M:%S', time.localtime())})
    wx.SendMsg("\n".join(output))

def reply(msgs, wx):
    for msg in msgs:
        if msg.type == 'friend':
            reply = msg.content
            print(f"消息：{reply}")
            handleMsg(wx, msg.sender, reply)

def main():
    wx = WeChat()
    listen_targets = parse_arguments()  # 从命令行获取参数[1,8](@ref)

    print(f"启动监听，目标对象：{', '.join(listen_targets)}")

    for target in listen_targets:
        print(f'正在添加监听对象：{target}')
        wx.AddListenChat(who=target)
    # 开启机器人  查询当前金额

    while True:
        try:
            msgs = wx.GetListenMessage()
            for chat in msgs:
                msg = msgs.get(chat)   # 获取消息内容
                print(f"{chat}")

                reply(msg, chat)
            time.sleep(0.3)

        except KeyboardInterrupt:
            print('\nBye~')
            os._exit(0)
            break
        except:
            print('意外错误')
            traceback.print_exc()
            time.sleep(LISTEN_INTERVAL)

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print('\nBye~')
        os._exit(0)